;(function () {
  // # infer 约束
  // - 在某些时候，我们可能对 infer 提取的类型值有些要求，比如我只想要数组第一个为字符串的成员，如果第一个成员不是字符串，那我就不要了。
  type FirstArrayItemType<T extends any[]> = T extends [infer P, ...any[]] ? P : never

  type test1 = FirstArrayItemType<[string, number, boolean]>

  // 加上对提取字符串的条件类型：
  type FirstArrayItemType1<T extends any[]> = T extends [infer P, ...any[]] ? (P extends string ? P : never) : never
  type test2 = FirstArrayItemType1<[string, number, boolean]>
  type Tmp1 = FirstArrayItemType1<[599, 'linbudu']> // never
  type Tmp2 = FirstArrayItemType1<['linbudu', 599]> // 'linbudu'
  type Tmp3 = FirstArrayItemType1<['linbudu']> // 'linbudu'

  //看起来好像能满足需求，但程序员总是精益求精的。泛型可以声明约束，只允许传入特定的类型，那 infer 中能否也添加约束，只提取特定的类型？TypeScript 4.7 就支持了 infer 约束功能来实现对特定类型地提取，比如上面的例子可以改写为这样：

  type FirstArrayItemType2<T extends any[]> = T extends [infer P extends string, ...any[]] ? P : never

  type Tmp4 = FirstArrayItemType2<['linbudu']> // 'linbudu'
})()
